package cool.doudou.doudada.message.core.signer;

import cool.doudou.doudada.cipher.algorithm.util.HmacUtil;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * AliSigner
 *
 * @author jiangcs
 * @since 2022/08/24
 */
public class AliSigner {
    /**
     * 获取 签名
     *
     * @param accessSecret 密钥
     * @param method       请求方法
     * @param urlParam     URL参数
     * @return 签名字符串
     */
    public static String get(String accessSecret, String method, Map<String, String> urlParam) {
        // 参数Key
        Map<String, String> paramMap = new TreeMap<>(urlParam);
        List<String> keyList = new ArrayList<>(paramMap.keySet());

        // 参数Key排序
        Collections.sort(keyList);

        // 构造请求字符串
        String queryString = constructQueryString(keyList, paramMap);

        // 计算签名值
        return computeSignatureValue(accessSecret, method, queryString);
    }

    /**
     * 构造请求字符串
     *
     * @param keyList  ascii排序key集合
     * @param paramMap 请求参数
     * @return 规范化字符串
     */
    private static String constructQueryString(List<String> keyList, Map<String, String> paramMap) {
        // 拼接参数
        StringBuilder sbSignatureValue = new StringBuilder();
        for (String key : keyList) {
            if (sbSignatureValue.length() > 0) {
                sbSignatureValue.append("&");
            }
            sbSignatureValue.append(URLEncoder.encode(key, StandardCharsets.UTF_8))
                    .append("=")
                    .append(URLEncoder.encode(paramMap.get(key), StandardCharsets.UTF_8));
        }
        return sbSignatureValue.toString();
    }

    /**
     * 计算签名值
     *
     * @param accessSecret 密钥
     * @param method       请求方法
     * @param queryString  请求字符串
     * @return 签名值
     */
    private static String computeSignatureValue(String accessSecret, String method, String queryString) {
        String signString = method + "&" + URLEncoder.encode("/", StandardCharsets.UTF_8) + "&" +
                URLEncoder.encode(queryString, StandardCharsets.UTF_8);
        return HmacUtil.sha1(accessSecret + "&", signString);
    }
}
